// wsClient.ts
import WebSocket from 'ws'
import { getWindow, getWindowManage } from './windowProxy'

// ---- Types ----
type Nullable<T> = T | null

// 如果你在 Electron 环境，也可以把 WindowLike 换成 Electron.BrowserWindow
interface WindowLike {
  webContents: { send: (channel: string, ...args: any[]) => void }
  setResizable?: (resizable: boolean) => void
  setMinimumSize?: (width: number, height: number) => void
  setSize?: (width: number, height: number) => void
  close?: () => void
}

enum MessageType {
  JoinRoom = 1, // 加入房间
  SendPeer = 2, // 发送 peer
  LeaveRoom = 3, // 退出房间
  EndMeeting = 4, // 结束会议
  ChatText = 5, // 聊天 文本消息
  Media = 6, // 媒体消息
  MediaUpdate = 7, // 媒体消息更新
  FriendRequest = 8, // 好友申请消息
  InviteMeeting = 9, // 邀请入会
  ForceKick = 10, // 被强制退出
  ToggleVideo = 11, // 用户开启关闭视频
  FriendRequestHandled = 12 // 处理好友申请
}

// 按需扩展你的服务端消息结构
interface WsIncomingMessage {
  messageType: MessageType
  [key: string]: any
}

// ---- State ----
let ws: Nullable<WebSocket> = null
const maxRetries = 5
const retryInterval = 2000
let retryCount = 0

const HEARTBEAT_INTERVAL = 5000
let heartBeatTimer: Nullable<NodeJS.Timeout> = null

let wsUrl: Nullable<string> = null
let needReconnect = false
let currentUserInfo: Nullable<any> = null

// ---- Public API ----
/**
 * 初始化WebSocket连接
 * @param _wsUrl WebSocket服务器地址
 * @param userInfo 用户信息对象
 */
const initWs = (_wsUrl: string, userInfo: any = null): void => {
  wsUrl = _wsUrl
  currentUserInfo = userInfo
  needReconnect = true
  connectWs()
}

const wsCheck = (): boolean => {
  return true
}

const connectWs = (): void => {
  // 记录连接的用户信息
  if (currentUserInfo) {
    console.log(`用户 ${currentUserInfo || '未知用户'} 正在连接WebSocket`)
  } else {
    console.log('未知用户正在连接WebSocket')
  }

  if (ws && (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING)) {
    console.log('已经连接上')
    return
  }

  if (!wsUrl) {
    console.error('wsUrl 未设置，无法建立连接')
    return
  }

  console.log(`尝试链接.....(重试次数：${retryCount}/${maxRetries}, 连接地址: ${wsUrl})`)
  ws = new WebSocket(wsUrl)

  ws.onopen = () => {
    if (retryCount > 0 && wsCheck()) {
      const mainWindow = getWindow('main') as unknown as WindowLike | undefined
      mainWindow?.webContents.send('reconnect', true)
    }
    retryCount = 0
    // 连接成功时显示用户信息
    if (currentUserInfo) {
      console.log(`用户 ${currentUserInfo || '未知用户'} websocket连接成功`)
    } else {
      console.log('websocket连接成功')
    }
    startHeartBeat()
  }

  ws.onmessage = (event: WebSocket.MessageEvent) => {
    try {
      const raw = event.data
      const text = typeof raw === 'string' ? raw : raw.toString()
      const data = JSON.parse(text) as WsIncomingMessage
      console.log('收到ws消息', data)
      console.log(data.messageType)
      const meetingWin = getWindow('main') as unknown as WindowLike | undefined

      const mainWin = getWindow('main') as unknown as WindowLike | undefined

      switch (data.messageType) {
        case MessageType.JoinRoom:
        case MessageType.SendPeer:
        case MessageType.LeaveRoom:
          if (
            mainWin &&
            (data.messageType === MessageType.JoinRoom ||
              data.messageType === MessageType.LeaveRoom)
          ) {
            mainWin.webContents.send('mainMessage', data)
          }
          if (meetingWin) {
            meetingWin.webContents.send('meetingMessage', data)
          }
          break

        case MessageType.EndMeeting:
          if (mainWin) mainWin.webContents.send('mainMessage', data)
          if (meetingWin) meetingWin.webContents.send('meetingMessage', data)
          break

        case MessageType.ChatText:
        case MessageType.Media:
        case MessageType.MediaUpdate:
          if (!meetingWin) return
          meetingWin.webContents.send('chatMessage', data)
          break

        case MessageType.FriendRequest:
          console.log('收到FriendRequest消息')
          if (!mainWin) {
            console.log('主窗口不存在，无法发送消息')
            return
          }
          console.log('--------')
          console.log('准备发送friendRequest消息到主窗口', data)
          try {
            mainWin.webContents.send('friendRequest', data)
            console.log('friendRequest消息发送成功')
          } catch (error) {
            console.error('发送friendRequest消息失败:', error)
          }
          break

        case MessageType.FriendRequestHandled:
        case MessageType.InviteMeeting:
        case MessageType.ForceKick:
          if (!mainWin) return
          mainWin.webContents.send('mainMessage', data)
          break

        case MessageType.ToggleVideo:
          if (!meetingWin) return
          meetingWin.webContents.send('meetingMessage', data)
          break

        default:
          // 未知类型，按需处理
          break
      }
    } catch (err) {
      console.error('解析 ws 消息失败：', err)
    }
  }

  ws.onerror = () => {
    // 主动关闭以触发 onclose 统一重连逻辑
    ws?.close()
  }

  ws.onclose = () => {
    clearHeartbeatTimers()
    handleReconnect()
  }
}

const handleReconnect = (): void => {
  if (!needReconnect) return

  if (retryCount >= maxRetries) {
    console.error('已经到达最大重试次数，停止重试')
    retryCount = 0
    if (wsCheck()) {
      logout(false)
    }
    return
  }

  retryCount += 1
  const delay = retryInterval * Math.pow(1.5, retryCount - 1)
  console.log(`连接断开, 等待 ${Math.round(delay / 100) / 10}s 后重试`)

  if (wsCheck()) {
    const mainWindow = getWindow('main') as unknown as WindowLike | undefined
    mainWindow?.webContents.send('reconnect', false)
  }

  setTimeout(() => {
    connectWs()
  }, delay)
}

const startHeartBeat = (): void => {
  clearHeartbeatTimers()
  heartBeatTimer = setInterval(() => {
    if (ws?.readyState === WebSocket.OPEN) {
      try {
        ws.send('ping')
      } catch (e) {
        console.error('发送心跳失败：', e)
      }
    }
  }, HEARTBEAT_INTERVAL)
}

const clearHeartbeatTimers = (): void => {
  if (heartBeatTimer) {
    clearInterval(heartBeatTimer)
    heartBeatTimer = null
  }
}

const logout = (closeWs: boolean = true): void => {
  //   const login_width = 375
  //   const login_height = 365
  //   const mainWindow = getWindow('main') as unknown as WindowLike | undefined

  //   // 记录登出的用户信息
  //   if (currentUserInfo) {
  //     console.log(`用户 ${currentUserInfo.username || '未知用户'} 已登出`)
  //   }

  //   // 这些方法在 WindowLike 上是可选的，按需判断
  //   mainWindow?.setResizable?.(true)
  //   mainWindow?.setMinimumSize?.(login_width, login_height)
  //   mainWindow?.setSize?.(login_width, login_height)
  //   mainWindow?.setResizable?.(false)

  if (closeWs) {
    needReconnect = false
    ws?.close()
  }

  //   // 清空用户信息
  //   currentUserInfo = null

  //   const windows = getWindowManage() as unknown as Record<string, WindowLike>
  //   for (const winKey in windows) {
  //     if (Object.prototype.hasOwnProperty.call(windows, winKey)) {
  //       if (winKey !== 'main') {
  //         windows[winKey]?.close?.()
  //       }
  //     }
  //   }
  //   mainWindow?.webContents.send('logout')
}

const sendWsData = (data: string | Buffer | ArrayBuffer | Buffer[]): void => {
  if (!ws || ws.readyState !== WebSocket.OPEN) return
  ws.send(data)
}

export { initWs, logout, sendWsData, MessageType, type WsIncomingMessage }
